#include "Encoder/include/encipher.h"
Encipher* Encipher::encipher=nullptr;
std::string Encipher::aeskey;
std::string Encipher::aesiv;

Encipher::Encipher(){}



void Encipher::setAesiv(const std::string &vi)
{
    aesiv=vi;
}

void Encipher::setAesKey(const std::string &key)
{
    aeskey=key;
}



// 辅助函数，将二进制数据转换为十六进制字符串

std::string Encipher::toHex(const unsigned char* data, size_t length) {

    std::stringstream ss;

    for (size_t i = 0; i < length; ++i) {

        ss << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];

    }

    return ss.str();

}



std::unique_ptr<std::string> Encipher::sha256EVP(const std::string &input) {

    EVP_MD_CTX* ctx = EVP_MD_CTX_new();

    if (!ctx) {

        // 处理错误，例如通过抛出异常或返回空指针

        throw std::runtime_error("EVP_MD_CTX_new failed");

    }



    if (1 != EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr)) {

        EVP_MD_CTX_free(ctx);

        throw std::runtime_error("EVP_DigestInit_ex failed");

    }



    if (1 != EVP_DigestUpdate(ctx, input.c_str(), input.length())) {

        EVP_MD_CTX_free(ctx);

        throw std::runtime_error("EVP_DigestUpdate failed");

    }



    unsigned char result[SHA256_DIGEST_LENGTH];

    unsigned int len = 0;

    if (1 != EVP_DigestFinal_ex(ctx, result, &len)) {

        EVP_MD_CTX_free(ctx);

        throw std::runtime_error("EVP_DigestFinal_ex failed");

    }



    EVP_MD_CTX_free(ctx); // 释放 EVP_MD_CTX



    // 将哈希值转换为十六进制字符串

    std::string hexResult = toHex(result, len);

    return std::make_unique<std::string>(hexResult);

}

bool Encipher::validate(const std::string &mes,const std::string& sha256value)
{
    return !sha256value.compare(*Encipher::sha256EVP(mes));
}


std::string removePadding(const std::string& data) {
        if (data.empty()) {
            return data;
        }

        int padding = data[data.size() - 1];
        if (padding > AES_BLOCK_SIZE || padding == 0) {
            throw std::runtime_error("无效的填充");
        }

        for (int i = 1; i <= padding; ++i) {
            if (data[data.size() - i] != padding) {
                throw std::runtime_error("无效的填充");
            }
        }

        return data.substr(0, data.size() - padding);
    }


std::unique_ptr<std::string> Encipher::aesDecryptEVP(std::string& data)
{
    // 创建一个缓冲区来保存解密后的内容
    char* decData = nullptr;
    int decLen = 0;

    // 初始化EVP上下文
    EVP_CIPHER_CTX* ctx2 = EVP_CIPHER_CTX_new();

    // 初始化解密上下文
    EVP_CipherInit_ex(ctx2, EVP_aes_256_cbc(), NULL, (const unsigned char*)aeskey.data(), (const unsigned char*)aesiv.data(), 0); // 0 表示解密


    // 分配足够的内存给解密后的数据
    decLen = data.size() + AES_BLOCK_SIZE; // 为了安全起见，预留足够的空间
    decData = new char[decLen];

    // 解密数据
    int outlen = decLen;
    EVP_CipherUpdate(ctx2, (unsigned char*)decData, &outlen, (const unsigned char*)data.data(), data.size());
    decLen = outlen;
    if (!EVP_CipherFinal(ctx2, (unsigned char*)(decData + outlen), &outlen)) {
        // 处理错误情况
        ERR_print_errors_fp(stderr);
        std::cout<<("Failed to finalize decryption.")<<std::endl;
    }
    decLen += outlen;

    // 清理上下文
    EVP_CIPHER_CTX_free(ctx2);

    // 构造QByteArray
    std::string* res=new std::string(decData, decLen);

    // 释放分配的内存
    delete[] decData;

    return std::unique_ptr<std::string>(res);
}




std::unique_ptr<std::string> Encipher::aesEncryptEVP(std::string &data) {
    // 创建一个足够大的输出缓冲区，AES加密可能会输出与输入相同大小的数据，但CBC模式通常需要填充到块大小
    int outlen = data.size() + AES_BLOCK_SIZE - (data.size() % AES_BLOCK_SIZE);
    char* encData = new char[outlen];
    int len;

    // 初始化加密上下文
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, (const unsigned char*)aeskey.data(), (const unsigned char*)aesiv.data(), 1);

    // 执行加密操作
    int encryptedLen = 0;
    EVP_CipherUpdate(ctx, (unsigned char*)encData, &len, (const unsigned char*)data.data(), data.size());
    encryptedLen += len;

    // 完成加密，包括填充
    int finalLen;
    EVP_CipherFinal_ex(ctx, (unsigned char*)encData + encryptedLen, &finalLen);
    encryptedLen += finalLen;

    // 清理上下文
    EVP_CIPHER_CTX_free(ctx);

    // 创建并返回QByteArray
    std::string* result=new std::string(encData, encryptedLen);
    delete[] encData; // 不要忘记释放内存
    return std::unique_ptr<std::string>(result);
}
